package com.ssc.manager.common.system;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.ssc.manager.admin.entity.db.Bet;
import com.ssc.manager.admin.entity.db.Play;
import com.ssc.manager.admin.entity.db.UserAccount;
import com.ssc.manager.common.constant.SystemConstant;
import com.ssc.manager.common.utils.BetiingUtils;
import com.ssc.manager.trading.core.BettingQueue;

public class SystemData {
	
	/**
	 * 玩法集合
	 */
	public static  Map<String,Play> plays = new ConcurrentHashMap<String,Play>();  
	
	/**
	 * 交易项集合
	 */
	public static  Map<String,List<String>> items = new ConcurrentHashMap<String,List<String>>();  
	
	/**
	 * 注单任务 对列
	 */
	public static Map<String,BettingQueue> bettingQueueMap = new ConcurrentHashMap<String,BettingQueue>();
	
	/**
	 * 用户列表 
	 */
	public static Map<String,UserAccount> userAccountMap = new ConcurrentHashMap<String,UserAccount>();
	
	/**
	 * 交易项赔率列表
	 */
	//private static Map<String,List<BigDecimal>> oddsmap = new ConcurrentHashMap<String,List<BigDecimal>>();
	
	/**
	 * 交易项待交易注单列表
	 */
	private static Map<String,ConcurrentHashMap<Double,List<Bet>>> oddsItems = new ConcurrentHashMap<String,ConcurrentHashMap<Double,List<Bet>>>(); 
	
	/**
	 * 用户注单列表
	 */
	private static Map<String,List<Bet>> userBets = new ConcurrentHashMap<String,List<Bet>>();
	
	/**
	 * 展示数据汇总
	 */
	private static Map<String,ConcurrentHashMap<Double,Double>> sumData = new ConcurrentHashMap<String,ConcurrentHashMap<Double,Double>>();
	/**
	 * 
	 *
	*//*
	public static ConfigDto systemConfig ;
	*/
	
	//================基础=====================
	/**
	 * 连接符
	 * @return
	 */
	public static String findBetListKey(String userid){
		return SystemConstant.BETKEY+SystemConstant.CONNECT+userid;
	}
	
	
	/*public static ConfigDto getSystemConfig() {
		return systemConfig;
	}
	public static void setSystemConfig(ConfigDto systemConfig) {
		SystemData.systemConfig = systemConfig;
	}*/
	

	//====================用户============================
	public static UserAccount findUserAccount(String userid){
		return userAccountMap.get(userid);
	}
	
	public static void addUserAccount(UserAccount user){
		if(null == user) return;
		userAccountMap.put(String.valueOf(user.getUaccId()), user);
	}
	
	
	//======================玩法===================
	/**
	 * 
	* 方法名称: addPlay
	* 描述:加入玩法
	* 参数：@param play 
	* @throws
	 */
	public static void addPlay(Play play){
		String playkey = String.valueOf(play.getId());
		Play p = plays.get(playkey);
		if(null == p){
			p = play;
			plays.put(playkey, p);
		}
	}

	/**
	 * 查询玩法
	 * @param playid
	 * @return
	 */
	public static Play findPlay(String playid){
		return  plays.get(playid);
	}
	
	public static void addItem(String gameCode,List<String>list){
		if(!items.containsKey(gameCode)){
			items.put(gameCode, list);
		}
	}
	
	public static  long findItemByIndex(String gameCode,String itemKey){
		return Long.valueOf(items.get(gameCode).indexOf(itemKey));
	}
	
	public static String findCodeByBet(Bet bet){
		Play play = findPlay(String.valueOf(bet.getPlayId()));
		return play.getGameCode();
	}
	
	/**
	 * 玩法是否存在
	 * @param playid
	 * @return
	 */
	public static boolean isLivePlay(String playid){
		return plays.containsKey(playid);
	}
	
	//====================注单=======================
	/**
	 * 根据玩法id 查询取betquerue
	 * @param playid
	 * @return
	 */
	public static BettingQueue findBettingQueue(String playid){
		String playkey = BetiingUtils.findPlaykey(playid);
		return findAddBettingQueue(playkey);
	}
	
	/**
	 * 查询betingqueue方法
	* 方法名称: findAddBettingQueue
	* 描述:
	* 参数：@param betkey
	* 参数：@return 
	* @throws
	 */
	public static BettingQueue findAddBettingQueue(String betkey){
		BettingQueue betting =  bettingQueueMap.get(betkey);
		if(null == betting){
			betting = new BettingQueue();
			new Thread(betting).start();
			bettingQueueMap.put(betkey, betting);
		}
		return betting;
	}
	
	
	/**
	 * 
	* 方法名称: findOddsKey
	* 描述:获取最优赔率 卖永远是赔率越小越好，买是越高越好
	* 参数：@param od 
	* 参数：@param oddsKey key
	* 参数：@param tradeType 方向
	* 参数：@param change 是否转换
	* 参数：@return 如果返回空代表没有合理的数据
	* @throws
	 */
	public static Double findGoodOddsKey(Double od,String oddsKey,String tradeType,boolean change){
		BigDecimal d = BigDecimal.valueOf(od);
		Double[] keys = findOddsList(oddsKey);
		if(null == keys) return null;
		if(!change && !SystemConstant.TRADEBUY.equals(tradeType)){
			for(int i=keys.length-1;i>=0;i--){
				Double odds = keys[i];
				BigDecimal temodds;
				if(change){
					temodds =  SystemConstant.DFACTOR.divide(SystemConstant.DFACTOR.multiply(BigDecimal.valueOf(odds)),2,BigDecimal.ROUND_DOWN);
				}else{
					temodds = BigDecimal.valueOf(odds);
				}
				
				if(!SystemConstant.TRADEBUY.equals(tradeType)){
					if(temodds.compareTo(d) <= 0){
						return odds;
					}
				}else{
					if(temodds.compareTo(d) >= 0){
						return odds;
					}
				}
			}
		}else{
			for(Double odds : keys){
				BigDecimal temodds;
				if(change){
					temodds =  SystemConstant.DFACTOR.divide(SystemConstant.DFACTOR.multiply(BigDecimal.valueOf(odds)),2,BigDecimal.ROUND_DOWN);
				}else{
					temodds = BigDecimal.valueOf(odds);
				}
				
				if(!SystemConstant.TRADEBUY.equals(tradeType)){
					if(temodds.compareTo(d) <= 0){
						return odds;
					}
				}else{
					if(temodds.compareTo(d) >= 0){
						return odds;
					}
				}
			}
		}
		return null;
	}
	/**
	 * ***********************用户注单*************************
	 */
	
	public static void addUserBet(Bet bet){
		List<Bet> list = userBets.get(String.valueOf(bet.getUserId()));
		if(null == list){
			list = new ArrayList<Bet>();
			userBets.put(String.valueOf(bet.getUserId()), list);
		}
		synchronized (list) {
			list.add(bet);
		}
	}
	
	/**
	 * 删除用户缓存中一个注单信息
	 * @param bet
	 */
	public static void rmUserBet(Bet bet){
		List<Bet> list = userBets.get(String.valueOf(bet.getUserId()));
		if(null == list) return;
		synchronized (list) {
			list.remove(list);
		}
	}
	
	/**
	 * 查询userbet
	 * @param userId
	 * @return
	 */
	public static List<Bet> findUserBet(Integer userId){
		return userBets.get(String.valueOf(userId));
	}
	
	/**********************注單****************************/
	/**
	 * 
	* 方法名称: addBetDto
	* 描述:增加betdto
	* 参数：@param betDto
	* 参数：@param oddskey 
	* @throws
	 */
	public static void addBet(Bet bet){
		String oddskey = BetiingUtils.findBetKey(bet.getItemCode(), bet.getTradeType());
		addBets(bet,oddskey);
		//findAddOddsList(bet.getOdds(),oddskey);
	}
	
	/**
	 * 
	 * @param bet
	 * @param money
	 * @param type 1为增加 -1为减少
	 */
	public static List<Double[]> addSumData(Bet bet,Double money,String type){
		
		List<Double[]> sum = new ArrayList<Double[]>();
		
		Play play = findPlay(String.valueOf(bet.getPlayId()));
		String oddskey = BetiingUtils.findItemKey(play.getGameCode(),play.getPlayCode(),play.getItemCode(), bet.getTradeType());
		
		ConcurrentHashMap<Double,Double> sumMap = sumData.get(oddskey);
		synchronized (sumMap) {
			if(null == sumMap){
				sumMap = new ConcurrentHashMap<Double,Double>();
				sumData.put(oddskey, sumMap);
			}
			Double sumMoney = sumMap.get(bet.getOdds());
			if(null == sumMoney){
				sumMap.put(bet.getOdds(), 0D);
			}
			
			if(SystemConstant.BET_SUM_ADD.equals(type)){
				sumMap.put(bet.getOdds(), sumMap.get(bet.getOdds())+money);
			}else{
				sumMap.put(bet.getOdds(), sumMap.get(bet.getOdds())-money);
			}
			
			Set<Double> keySet = sumMap.keySet();
			Double[] keys = new Double[keySet.size()];  
			keySet.toArray(keys);  
			Arrays.sort(keys);
			
			for(int i=keys.length-1;i>0;i--){
				if(3 == sum.size())break;
				Double odd = keys[i];
				Double itemManey = sumMap.get(odd);
				if(itemManey <=0d){
					continue;
				}
			}
			return sum;
		}
	}
	/**
	 * 根據bet和key查詢bet列表
	 * @param bet
	 * @param oddskey
	 * @return
	 */
	public static List<Bet> addBets(Bet bet,String oddskey){
		ConcurrentHashMap<Double,List<Bet>> betmap = oddsItems.get(oddskey);
		if(null == betmap){
			betmap = new ConcurrentHashMap<Double,List<Bet>>();
			oddsItems.put(oddskey, betmap);
		}
		List<Bet> betlist = betmap.get(bet.getOdds());
		if(null == betlist){
			betlist = new ArrayList<Bet>();
			betmap.put(bet.getOdds(), betlist);
		}
		betlist.add(bet);
		return betlist;
	}
	
	
	/**
	 * 如果注單列表為空，將列表清除并返回false
	 * @param odds
	 * @param oddskey
	 * @return
	 */
	public static boolean isLiveBet(Double odds,String oddskey){
		List<Bet> list = oddsItems.get(oddskey).get(odds);
		if(null == list)return false;
		synchronized (list) {
			if(0==list.size()){
				oddsItems.get(oddskey).remove(odds);
				return false;
			}else{
				return true;
			}
		}
	}
	
	/**
	 * 根据key和赔率查询注单列表
	 * @param odds
	 * @param oddskey
	 * @return
	 */
	public static  List<Bet> findBets(Double odds,String oddskey){
		ConcurrentHashMap<Double,List<Bet>> betmap = oddsItems.get(oddskey);
		if(null == betmap){
			return null;
		}
		return  betmap.get(odds);
	}
	
	
	

	public static void removeBetByBet(Bet bet){
		String oddskey = BetiingUtils.findBetKey(bet.getItemCode(), bet.getTradeType());
		rmBet(bet,oddskey);
	}

	
	//=======================find====================
	
	private static void rmBet(Bet bet,String oddskey){
		List<Bet> betlist = findBets(bet.getOdds(),oddskey);
		if(null == betlist) return;
		synchronized (betlist) {
			if(betlist.size()==0) {
				oddsItems.get(oddskey).remove(bet.getOdds());
				//oddsmap.get(oddskey).remove(BigDecimal.valueOf(bet.getOdds()));
			}else{
				betlist.remove(bet);
			}
		}
	}
	
	
	/**********************赔率********************/
	/**
	 * 查询赔率列表
	 * @param oddskey
	 * @return
	 */
	public static Double[] findOddsList(String oddskey){
		if(!oddsItems.containsKey(oddskey)){
			return null;
		}
		Set<Double> keySet = oddsItems.get(oddskey).keySet();
		Double[] keys = new Double[keySet.size()];  
		keySet.toArray(keys);  
		return keys;
	}
	
	/**
	 * 查詢并添加賠率列表
	 * @param odds
	 * @param oddskey
	 * @return
	 *//*
	private static List<BigDecimal> findAddOddsList(Double odds,String oddskey){
		BigDecimal bigOdds = BigDecimal.valueOf(odds);
		List<BigDecimal> listodds = findOddsList(oddskey);
		
		synchronized (listodds) {
			if(!listodds.contains(bigOdds)){
				listodds.add(bigOdds);
			}
			Collections.sort(listodds, Collections.reverseOrder());
		}
		return listodds;
	}*/
	
	
	
	
	
	

	
}
